from flask import Flask, request, Response, jsonify

from douzero.evaluation.deep_agent import DeepAgent
from douzero.env.autoeditor_game import GameEnv
import os 
            
EnvCard2RealCard = {3: '3', 4: '4', 5: '5', 6: '6', 7: '7',
                    8: '8', 9: '9', 10: '10', 11: 'J', 12: 'Q',
                    13: 'K', 14: 'A', 17: '2', 20: 'X', 30: 'D'}
# 所有key对应的GameEnv. 键值对:key-->GameEnv 
game_environments = {}
# 所有key对应的玩家AI。键值对:key-->DeepAgent 
player_agents = {}
model_paths = {
        'landlord': "baselines/douzero_WP/landlord.ckpt",
        'landlord_up': "baselines/douzero_WP/landlord_up.ckpt",
        'landlord_down': "baselines/douzero_WP/landlord_down.ckpt"}
class Player:

    def __init__(self):
        self.cards = []
        self.deep_agent = None
    #更新角色的出牌信息
    def update_player_action(self, cards):
        self.cards = cards 

    def act(self, infoset):
        return self.cards 


app = Flask(__name__)

#用于检测key是否有效
def check_key_vaild(key) :
    return True 

def get_request_param(request, key, method='both'):
    if method == 'post':
        return request.form.get(key)
    elif method == 'get':
        return request.args.get(key)
    else:
        return request.form.get(key) or request.args.get(key)

def validate_request_param(request, required_params):
    for param in required_params:
        if not get_request_param(request, param):
            return False, f"{param} required"
    return True, None

def setup_game_environment(key, player_position, player_hand_cards, three_landlord_cards):
    if key in game_environments:
        game_env = game_environments[key]
        game_env.reset()
    else:
        players = {pos: Player() for pos in ['landlord', 'landlord_up', 'landlord_down']}
        game_env = GameEnv(players)
        game_environments[key] = game_env
    game_env.card_play_init(player_position, player_hand_cards, three_landlord_cards)

@app.route('/agent_init', methods=['POST', 'GET'])
def agent_init():
    result = {"code": "0", "message": "success"}
    valid, msg = validate_request_param(request, ['key', 'player_position', 'player_hand_cards', 'three_landlord_cards'])
    if not valid:
        result["code"] = -1
        result["message"] = msg
        return jsonify(result)

    key = get_request_param(request, 'key')
    player_position = get_request_param(request, 'player_position')
    player_hand_cards_str = get_request_param(request, 'player_hand_cards')
    three_landlord_cards_str = get_request_param(request, 'three_landlord_cards')

    if not check_key_vaild(key):
        result["code"] = -1
        result["message"] = "key invalid"
        return jsonify(result)

    player_hand_cards = [int(card) for card in player_hand_cards_str.split(',')]
    three_landlord_cards = [int(card) for card in three_landlord_cards_str.split(',')]

    try:
        setup_game_environment(key, player_position, player_hand_cards, three_landlord_cards)
        ai = DeepAgent(player_position, model_paths[player_position])
        player_agents[key] = ai
    except Exception as e:
        result["code"] = -1
        result["message"] = f"Initialization failed: {str(e)}"
        return jsonify(result)

    return jsonify(result)

@app.route('/get_obs', methods=['GET'])
def get_obs():
    result = {"code": "0", "message": "success", "data": []}
    valid, msg = validate_request_param(request, ['key'])
    if not valid:
        result["code"] = -1
        result["message"] = msg
        return jsonify(result)

    key = get_request_param(request, 'key')
    if key not in game_environments:
        result["code"] = -1
        result["message"] = "key is invalid or not initialized"
        return jsonify(result)

    try:
        game_env = game_environments[key]
        action = player_agents[key].act(game_env.game_infoset)
        result["data"] = action
    except Exception as e:
        result["code"] = -1
        result["message"] = f"Error getting observation: {str(e)}"
    
    return jsonify(result)

@app.route('/action', methods=['POST', 'GET'])
def action():
    result = {"code": "0", "message": "success"}
    valid, msg = validate_request_param(request, ['key', 'player_position'])
    if not valid:
        result["code"] = -1
        result["message"] = msg
        return jsonify(result)

    key = get_request_param(request, 'key')
    if key not in game_environments:
        result["code"] = -1
        result["message"] = "key is invalid or not initialized"
        return jsonify(result)

    game_env = game_environments[key]
    player_position = get_request_param(request, 'player_position')
    played_cards_str = get_request_param(request, 'played_cards')

    if player_position != game_env.acting_player_position:
        del game_environments[key]
        return "Action error: Not current position. This round removed."

    try:
        player = game_env.players[player_position]
        played_cards = [int(card) for card in played_cards_str.split(',')] if played_cards_str else []
        player.update_player_action(played_cards)
        game_env.step()
    except Exception as e:
        result["code"] = -1
        result["message"] = f"Action failed: {str(e)}"

    return jsonify(result)

@app.route('/finish', methods=['POST', 'GET'])
def game_finish():
    result = {"code": "0", "message": "success"}
    valid, msg = validate_request_param(request, ['key'])
    if not valid:
        result["code"] = -1
        result["message"] = msg
        return jsonify(result)

    key = get_request_param(request, 'key')
    if key not in game_environments:
        result["code"] = -1
        result["message"] = "key is invalid or not initialized"
        return jsonify(result)

    try:
        del game_environments[key]
        del player_agents[key]
    except Exception as e:
        result["code"] = -1
        result["message"] = f"Cleanup failed: {str(e)}"

    return jsonify(result)
if __name__ == '__main__':
    os.environ["CUDA_VISIBLE_DEVICES"] = "0"
    app.run(host='0.0.0.0', port=8090)


